import java.util.concurrent.atomic.AtomicLong;  
  
public class IdGeneratorAAA {  
    // 自定义纪元时间，比如系统启动时间（这里用固定值示例）  
    private final long epoch = 1722083520000L;  
    // 序列号生成器，用于多线程环境下的并发控制  
    private final AtomicLong sequence = new AtomicLong(0);  
  
    // 假设我们想要的时间戳部分能够表示较长时间段内的唯一性  
    // 这里使用更大的模数来减少重复的风险，但请注意这也会限制ID的生成速率  
    // 假设我们想要的时间戳部分能覆盖约11.5天（1000000000毫秒 / 86400000毫秒/天）  
    private static final long TIME_PART_MOD = 1000000000L;  
  
    // 序列号部分的最大值，这里设置为4095，即14位二进制能表示的最大值  
    // 注意：由于我们将序列号左移了14位，因此它实际上占用了ID的低14位  
    private static final long SEQUENCE_MASK = 0x3FFF; // 4095 in hex  
  
    // 生成ID的方法  
    public String generateId(long memberId) {  
        // 当前时间戳与纪元时间的差值  
        long currentTimeMillis = System.currentTimeMillis();  
        long timeSinceEpoch = currentTimeMillis - epoch;  
  
        // 时间戳部分，取模以避免溢出，并减少重复风险  
        long timePart = timeSinceEpoch % TIME_PART_MOD;  
  
        // 序列号部分，使用AtomicLong保证线程安全  
        long nextSequence = sequence.getAndIncrement();  
        // 序列号部分需要确保在ID的14位内循环  
        long sequencePart = nextSequence & SEQUENCE_MASK;  
  
        // 将时间戳部分左移14位，然后与序列号部分进行位或操作，生成ID  
        long combined = (timePart << 14) | sequencePart;  
  
        // 如果需要，可以将memberId或其他信息也包含进ID中  
        // 但这里为了简单起见，我们只返回由时间戳和序列号组成的ID  
  
        return Long.toString(combined);  
    }  
  
    // 注意：这个方法没有直接使用memberId，但您可以在ID中包含它  
    // 例如，您可以将memberId的高位与combined进行某种形式的组合  
    // 这取决于您的具体需求和ID的用途

    public static void main(String[] args) {
        IdGeneratorAAA generator = new IdGeneratorAAA();
        long memberId = 123456789L;

        for (int i = 0; i <5 ; i++) {
            String id = generator.generateId(memberId);
            System.out.println("Generated ID: " + id);
        }

    }
}